package com.teach.service.impl;

import java.util.Arrays;
/**<pre>
 * TODO:验证码短信发送服务的阿里云实现
 * ClassName : com.teach.service.impl.SmsServiceByAliyun
 * Author : J.L.Zhou
 * Date : 2019年8月10日 下午10:29:29
 * Version : V1.0
 * Copyright 2019 jlzhou.top Inc. All rights reserved. 
 * Warning：本内容仅限于公司内部传阅，禁止外泄以及用于其他的商业目.</pre>
 */
import java.util.Map;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.teach.config.ConfigProperties;
import com.teach.exception.CodeException;
import com.teach.service.SmsCacheService;
import com.teach.service.SmsService;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * TODO:短信验证码的阿里云实现
 * ClassName : com.teach.service.impl.SmsServiceByAliyun
 * Author : J.L.Zhou
 * Date : 2019年8月10日 下午10:32:49
 * Version : V1.0
 * Copyright 2019 jlzhou.top Inc. All rights reserved. 
 * Warning：本内容仅限于公司内部传阅，禁止外泄以及用于其他的商业目.
 * </pre>
 */
@Service
@Slf4j
public class SmsServiceByAliyun implements SmsService {

	@Autowired
	private ConfigProperties config;

	@Autowired
	private ObjectMapper mapper;

	@Autowired
	private SmsCacheService cache;

	private Random random = new Random();

	@Override
	public String getRandomCode(int len) {
		String codes = config.sms.codes;
		StringBuffer sb = new StringBuffer();
		if (config.sms.enable) {
			for (int i = 0; i < len; i++) {
				sb.append(codes.charAt(random.nextInt(codes.length())));
			}
		} else {
			char[] c = new char[len];
			Arrays.fill(c, '1');
			sb.append(c);
		}
		log.debug("生成{}位验证码:{}", len, sb);
		return sb.toString();
	}

	@Override
	public String send(String tel) {
		String code = getRandomCode(6);
		send(tel, code);
		return code;
	}

	@Override
	public void send(String tel, String code) {
		log.debug("准备发送手机[{}]验证码[{}]", tel, code);
		if (cache.get(tel) != null) {
			throw new CodeException(61);
		}
		
		if(!config.sms.enable) {
			log.debug("模拟发送手机[{}]验证码[{}]",tel,code);
			cache.push(tel, code);
			log.debug("加入缓存：手机[{}]验证码[{}]", tel, code);
			return;
		}
		
		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", config.sms.aliyun.accessKeyId,
				config.sms.aliyun.accessKeySecret);
		IAcsClient client = new DefaultAcsClient(profile);

		CommonRequest request = new CommonRequest();
		request.setMethod(MethodType.POST);
		request.setDomain("dysmsapi.aliyuncs.com");
		request.setVersion("2017-05-25");
		request.setAction("SendSms");
		request.putQueryParameter("RegionId", "cn-hangzhou");
		request.putQueryParameter("PhoneNumbers", tel);
		request.putQueryParameter("SignName", config.sms.aliyun.signName + "a");
		log.debug("设置短信签名：{}", config.sms.aliyun.signName);
		request.putQueryParameter("TemplateCode", config.sms.aliyun.templateCode);
		log.debug("设置短信模板：{}", config.sms.aliyun.templateCode);
		request.putQueryParameter("TemplateParam", "{\"num\":\"" + code + "\"}");
		CommonResponse response = null;
		try {
			response = client.getCommonResponse(request);
			log.debug(response.getData());
			// {"Message":"OK","RequestId":"91B14A7F-8925-4E02-A2F7-8E0F361246B4","BizId":"191521375946448598^0","Code":"OK"}
			// {"Message":"签名不合法(不存在或被拉黑)","RequestId":"333CBAD9-A5B4-4D7E-B771-031F74F6D8B7","Code":"isv.SMS_SIGNATURE_ILLEGAL"}
		} catch (Exception e) {
			throw new CodeException(62, e);
		}
		Map<String, String> data = null;
		try {
			JavaType type = mapper.getTypeFactory().constructParametricType(Map.class, String.class, String.class);
			data = mapper.readValue(response.getData(), type);
		} catch (Exception e) {
			throw new CodeException(62, e);
		}
		if (data.get("Code").equalsIgnoreCase("ok")) {
			cache.push(tel, code);
			log.debug("加入缓存：手机[{}]验证码[{}]", tel, code);
		} else {
			throw new RuntimeException("发送短信失败：" + data.get("Message"));
		}
	}

	@Override
	public boolean check(String tel, String code) {
		String temp = cache.get(tel);
		log.debug("检查手机[{}]验证码[{}],缓存中掩码[{}]", tel, code, temp);
		if (temp == null) {
			throw new CodeException(63);
		}
		return temp.equals(code);
	}

}
